
package SemanticoPacote;


import SemanticoPacote.TratamentoErroSemantico.ErroSemantico;
import compilador_full.TabelaSimbolos;

/**
 *
 * @author Beto
 */
public class ExpressaoAritmetica {

    public void expAritmetica(TabelaSimbolos tabelaSimbolos, String escopo, String tipoDaAtribuicao) {

        // enquanto não for ;
       while (tabelaSimbolos.getTipo().equals("identificador") || tabelaSimbolos.getLookahead().equals("+") ||  tabelaSimbolos.getLookahead().equals("-") ||
               tabelaSimbolos.getLookahead().equals("*") || tabelaSimbolos.getLookahead().equals("/") ||
                    tabelaSimbolos.getTipo().equals("numero") || tabelaSimbolos.getLookahead().equals("(")) {

            // verifica qual sub grupo é
            // se for um identificador verifica se foi declarado e se é do mesmo tipo
            if (tabelaSimbolos.getTipo().equals("identificador")) {
                    String TipoAtual = "";
                    // verifica se o nome existe
                    if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {
                        System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada +");
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha()
                                            + ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  não foi declarada " );
                    } else {
                        // define o tipo da variável
                        if (tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead()).equals("")) {
                            // existe tipo
                            TipoAtual = tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo);
                        } else {
                            TipoAtual = tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead());
                        }
                    }
                    //
                    if (!TipoAtual.equals(tipoDaAtribuicao) && !tipoDaAtribuicao.equals("") && !TipoAtual.equals("")) {
                         System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + TipoAtual);
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    //
                    tabelaSimbolos.soConsome(); // consome o nome
            // se for um numero verifica se é do mesmo tipo
            } else if (tabelaSimbolos.getTipo().equals("numero")){
                    // verifica se os tipos são iguais
                    if (! tipoDaAtribuicao.equals(InformaTipo(tabelaSimbolos.getLookahead())) && !tipoDaAtribuicao.equals("")) {
                        System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + InformaTipo(tabelaSimbolos.getLookahead()) + " : "+ tabelaSimbolos.getLookahead() );
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    tabelaSimbolos.soConsome(); // consome o numero
            // operador so consome
            } else if (tabelaSimbolos.getTipo().equals("operador")){
                 tabelaSimbolos.soConsome(); // consome o operador
            // se for ( procura o ) e consome e faz a logica
            } else if (tabelaSimbolos.getLookahead().equals("(")){
                tabelaSimbolos.soConsome(); // consome (
                // chama ela mesma 
                expAritmetica(tabelaSimbolos, escopo, tipoDaAtribuicao);
                tabelaSimbolos.soConsome(); // consome )
            } else if (tabelaSimbolos.getTipo().equals("identificador") && tabelaSimbolos.superLookahead(1).equals("(")) {
                // chama chamada de função
                chamadaDeFuncao chamada = new chamadaDeFuncao(tabelaSimbolos);
                chamada.chamaFuncao(escopo);
            }

        }
    }

      // verifica se o numero é inteiro
      public String InformaTipo (String token) {
          // informa tipo
          if (token.equals("true") || token.equals("false"))
              return "boolean";
          if (token.charAt(0) == '\"' && token.length() > 3)
              return "frase";
          if (token.charAt(0) == '\"' && token.length() == 3)
              return "char";
          if (token.charAt(0) == '0' || token.charAt(0) == '1' || token.charAt(0) == '2' || token.charAt(0) == '3' || token.charAt(0) == '4' || token.charAt(0) == '5' ||
                  token.charAt(0) == '6' || token.charAt(0) == '7' || token.charAt(0) == '8' || token.charAt(0) == '9') {
              // verifica se o numero é inteiro
              for (int i = 0; i < token.length(); i++)
                    if (token.charAt(i) == '.') // se encontrar . é por que é float
                            return "float";
              // retorna se é um numero
              return "int";
          } else {
              return "variavel";
          }
      }

}
